package ar.com.muebleria.util;
import java.util.Date;
import java.util.Locale;
import java.text.SimpleDateFormat;
import java.text.NumberFormat;
import java.util.Currency;

public class ConvertionTools {

	/**
	 * <pre>
	 * Esta funcion esta destinada a convertir un String con una fecha en un
	 * objeto Date de java, para poder analizarlo.
	 * La conversion se hace utilizando el objeto SimpleDateFromat como convetor, por lo
	 * tanto la mascara se va a armar en base a lo requerido por ese objeto.
	 * 
	 * Letter  Date or Time Component  Presentation  	  Examples  
	 * G       Era designator          Text          	  AD  
     * y       Year                    Year          	  1996; 96  
     * M 	   Month in year  		   Month  	     	  July; Jul; 07  
     * w  	   Week in year  		   Number  		 	  27  
     * W  	   Week in month  		   Number  		 	  2  
     * D  	   Day in year  		   Number  			  189  
     * d  	   Day in month  		   Number  			  10  
     * F  	   Day of week in month    Number  			  2  
	 * E  	   Day in week 			   Text	   			  Tuesday; Tue  
	 * a  	   Am/pm marker  		   Text  		      PM  
	 * H  	   Hour in day (0-23)  	   Number  			  0  
	 * k  	   Hour in day (1-24)  	   Number  			  24  
	 * K  	   Hour in am/pm (0-11)    Number  			  0  
	 * h  	   Hour in am/pm (1-12)    Number  			  12  
	 * m  	   Minute in hour  		   Number  			  30  
	 * s  	   Second in minute  	   Number  			  55  
	 * S  	   Millisecond  		   Number             978  
	 * z  	   Time zone  			   General time zone  Pacific Standard Time; PST; GMT-08:00  
	 * Z  	   Time zone  			   RFC 822 time zone  -0800  
	 *
	 * </pre>
	 * @param parDate El String con la fecha a converit
	 * @param parMask La mascara que se va a utilizar
	 * @return El Date ya convertido
	 * @throws Exception En caso de que algun error de conversion ocurra
	 */
	public static Date toDate(String parDate, String parMask)
		throws Exception{
		try{
			//Creo el objeto para convertir y realizo su conversion
			SimpleDateFormat sdf = new SimpleDateFormat(parMask);
			return sdf.parse(parDate);
		}
		catch(Exception e){
			throw new Exception("Para String:\'"+parDate+"\'. "+e.getMessage());
		}
	}
	
	/**
	 * <pre>
	 * Esta funcion esta destinada a convertir un objeto Date de java con una fecha en un
	 * String de java, para poder analizarlo.
	 * La conversion se hace utilizando el objeto SimpleDateFromat como convetor, por lo
	 * tanto la mascara se va a armar en base a lo requerido por ese objeto.
	 * 
	 * Letter  Date or Time Component  Presentation  	  Examples  
	 * G       Era designator          Text          	  AD  
     * y       Year                    Year          	  1996; 96  
     * M 	   Month in year  		   Month  	     	  July; Jul; 07  
     * w  	   Week in year  		   Number  		 	  27  
     * W  	   Week in month  		   Number  		 	  2  
     * D  	   Day in year  		   Number  			  189  
     * d  	   Day in month  		   Number  			  10  
     * F  	   Day of week in month    Number  			  2  
	 * E  	   Day in week 			   Text	   			  Tuesday; Tue  
	 * a  	   Am/pm marker  		   Text  		      PM  
	 * H  	   Hour in day (0-23)  	   Number  			  0  
	 * k  	   Hour in day (1-24)  	   Number  			  24  
	 * K  	   Hour in am/pm (0-11)    Number  			  0  
	 * h  	   Hour in am/pm (1-12)    Number  			  12  
	 * m  	   Minute in hour  		   Number  			  30  
	 * s  	   Second in minute  	   Number  			  55  
	 * S  	   Millisecond  		   Number             978  
	 * z  	   Time zone  			   General time zone  Pacific Standard Time; PST; GMT-08:00  
	 * Z  	   Time zone  			   RFC 822 time zone  -0800  
	 *
	 * </pre>
	 * @param parDate El Date con la fecha a converit
	 * @param parMask La mascara que se va a utilizar
	 * @return El String ya convertido
	 * @throws Exception En caso de que algun error de conversion ocurra
	 */	
	public static String toString(Date parDate, String parMask)
	throws Exception{
		try{
			//Creo el objeto para convertir y realizo su conversion
			SimpleDateFormat sdf = new SimpleDateFormat(parMask);
			return sdf.format(parDate);
		}
		catch(Exception e){
			throw new Exception("Para Date:\'"+parDate+"\'. "+e.getMessage());
		}		
	}	
	
	/**
	 * Este metodo hace la conversion de un numero, en formato double, con todos los
	 * parametros por defecto.
	 * Toma el uso de numeros de Argentina.
	 * Establece una cantidad maxima de 10 digitos enteros y 2 fraccionados y minimo 
	 * de 0 enteros y  0 fraccionarios.
	 * @param parNumero El numero a convertir
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero)
	throws Exception{
		return toString(parNumero,1,10,0,2, "es", "AR", "ARS");
	}
	
	/**
	 * Este metodo hace la conversion de un numero, en formato double, siguiendo las
	 * especificaciones de los parametros.
	 * Toma el uso de numeros de Argentina.
	 * Establece una cantidad maxima de 10 digitos enteros y minimo de 0 enteros y 
	 * 0 fraccionarios, el maximo fraccionado se establecen en el parametro.
	 * @param parNumero El numero a convertir
	 * @param digitosFraccion Cantidad de digitos fraccionarios
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, int digitosFraccion)
	throws Exception{
		return toString(parNumero,0,10,0,digitosFraccion, "es", "AR", "ARS");
	}	
		
	/**
	 * Este metodo hace la conversion de un numero, en formato double, siguiendo las
	 * especificaciones de los parametros.
	 * Toma el uso de numeros de Argentina.
	 * Establece una cantidad maxima de 10 digitos enteros y minimo de 0 fraccionarios,
	 * el minimo de enteros y el maximo fraccionado se establecen en los parametros.
	 * @param parNumero El numero a convertir
	 * @param digitosEnteros Cantidad de digitos enteros
	 * @param digitosFraccion Cantidad de digitos fraccionarios
	 * @return El numero convertido 
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, int digitosEnteros, int digitosFraccion)
	throws Exception{
		return toString(parNumero,digitosEnteros,10,0,digitosFraccion, "es", "AR", "ARS");
	}	
	
	/**
	 * Este metodo hace la conversion de un numero, en formato double, siguiendo las
	 * especificaciones de los parametros.
	 * Toma el uso de numeros de Argentina.
	 * @param parNumero El numero a convertir
	 * @param intMin Cantidad minima de digitos enteros
	 * @param intMax Cantidad maxima de digitos enteros
	 * @param fracMin Cantidad minima de digitos fraccionarios
	 * @param fracMax Cantidad maxima de digitos fraccionarios
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, int intMin, int intMax, int fracMin, int fracMax)
	throws Exception{
		return toString(parNumero,intMin,intMax,fracMin,fracMax, "es", "AR", "ARS");
	}
	
	/**
	 * <pre>
	 * Este metodo hace la conversion de un Strign a un numero numero, en formato double, 
	 * siguiendo las especificaciones de los parametros, teniendo en cuentalas 
	 * especificaciones del pais, el idioma, y el uso de la moneda.
	 * 
	 * El idioma, es un codigo ISO 639-1 de 2 caracteres en minuscula.
	 * El pais, es un codigo ISO 3166-1 de 2 caracteres en mayusculas.
	 * El uso de la moneda es un codigo ISO 4217 de 3 caracteres en mayusculas.
	 * {@linkplain http://es.wikipedia.org/wiki/ISO_4217 ISO 4217}
	 * {@linkplain http://www.loc.gov/standards/iso639-2/englangn.html#st ISO 639}
	 * {@linkplain http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html ISO 3166}
	 * </pre>
	 * @param parNumero El numero a convertir
	 * @param intMin Cantidad minima de digitos enteros
	 * @param intMax Cantidad maxima de digitos enteros
	 * @param fracMin Cantidad minima de digitos fraccionarios
	 * @param fracMax Cantidad maxima de digitos fraccionarios
	 * @param idioma Idioma (ISO 639-1)
	 * @param pais Pais (ISO 3166-1)
	 * @param curr La moneda (ISO 4217)
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static double toDouble(String parNumero, int intMin, int intMax, int fracMin, int fracMax, String idioma, String pais, String curr)
	throws Exception{
		try{
			//Creo el objeto para convertir y realizo su conversion
			NumberFormat nf = NumberFormat.getInstance(new Locale(idioma,pais));
			nf.setCurrency(Currency.getInstance(curr));
			nf.setMinimumIntegerDigits(intMin);
			nf.setMaximumIntegerDigits(intMax);
			nf.setMinimumFractionDigits(fracMin);
			nf.setMaximumFractionDigits(fracMax);
			return nf.parse(parNumero).doubleValue();
		}
		catch(Exception e){
			throw new Exception("Para double:\'"+parNumero+"\'. "+e.getMessage());
		}				
	}
	
	/**
	 * <pre>
	 * Este metodo hace la conversion de un numero, en formato double, siguiendo las
	 * especificaciones de los parametros, teniendo en cuentalas especificaciones del 
	 * pais, el idioma, y el uso de la moneda.
	 * 
	 * El idioma, es un codigo ISO 639-1 de 2 caracteres en minuscula.
	 * El pais, es un codigo ISO 3166-1 de 2 caracteres en mayusculas.
	 * El uso de la moneda es un codigo ISO 4217 de 3 caracteres en mayusculas.
	 * {@linkplain http://es.wikipedia.org/wiki/ISO_4217 ISO 4217}
	 * {@linkplain http://www.loc.gov/standards/iso639-2/englangn.html#st ISO 639}
	 * {@linkplain http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html ISO 3166}
	 * </pre>
	 * @param parNumero El numero a convertir
	 * @param intMin Cantidad minima de digitos enteros
	 * @param intMax Cantidad maxima de digitos enteros
	 * @param fracMin Cantidad minima de digitos fraccionarios
	 * @param fracMax Cantidad maxima de digitos fraccionarios
	 * @param idioma Idioma (ISO 639-1)
	 * @param pais Pais (ISO 3166-1)
	 * @param curr La moneda (ISO 4217)
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, int intMin, int intMax, int fracMin, int fracMax, String idioma, String pais, String curr)
	throws Exception{
		try{
			//Creo el objeto para convertir y realizo su conversion
			NumberFormat nf = NumberFormat.getInstance(new Locale(idioma,pais));
			nf.setCurrency(Currency.getInstance(curr));
			nf.setMinimumIntegerDigits(intMin);
			nf.setMaximumIntegerDigits(intMax);
			nf.setMinimumFractionDigits(fracMin);
			nf.setMaximumFractionDigits(fracMax);
			return nf.format(parNumero);
		}
		catch(Exception e){
			throw new Exception("Para double:\'"+parNumero+"\'. "+e.getMessage());
		}				
	}
	
	/**
	 * Este metodo convierte un numero en double a un string siguiendo e interpretando una
	 * mascara en particular que debera armarse con una parte entera, una parte fraccionada
	 * ambas separadas por puntos.
	 * Los digitos deberan indicarse con un 9 que significa que el digito existe pero si no 
	 * esta presente en el numero que no lo coloque y el 0 indica que el digito se coloque
	 * igual, este o no este en el numero.
	 * Toma el uso de numeros de Argentina.
	 * @param parNumero El numero a convertir
	 * @param mascara La mascara para hacer la conversion
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, String mascara)
	throws Exception{
		return toString(parNumero,mascara, "es", "AR", "ARS");
	}
	
	/**
	 * Este metodo convierte un numero en double a un string siguiendo e interpretando una
	 * mascara en particular que debera armarse con una parte entera, una parte fraccionada
	 * ambas separadas por puntos.
	 * Los digitos deberan indicarse con un 9 que significa que el digito existe pero si no 
	 * esta presente en el numero que no lo coloque y el 0 indica que el digito se coloque
	 * igual, este o no este en el numero.
	 * Toma el uso de numeros de Argentina.
	 * @param parNumero El numero a convertir
	 * @param mascara La mascara para hacer la conversion
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static double toDouble(String parNumero, String mascara)
	throws Exception{
		return toDouble(parNumero,mascara, "es", "AR", "ARS");
	}
	
	/**
	 * <pre>
	 * Este metodo convierte un numero en double a un string siguiendo e interpretando una
	 * mascara en particular que debera armarse con una parte entera, una parte fraccionada
	 * ambas separadas por puntos.
	 * Los digitos deberan indicarse con un 9 que significa que el digito existe pero si no 
	 * esta presente en el numero que no lo coloque y el 0 indica que el digito se coloque
	 * igual, este o no este en el numero.
	 * Si no se coloca la parte fraccionaria, entonces se asume el numero como entero
	 * 
	 * Tiene en cuenta las especificaciones del idioma, el pais y la moneda
	 * 
	 * El idioma, es un codigo ISO 639-1 de 2 caracteres en minuscula.
	 * El pais, es un codigo ISO 3166-1 de 2 caracteres en mayusculas.
	 * El uso de la moneda es un codigo ISO 4217 de 3 caracteres en mayusculas.
	 * {@linkplain http://es.wikipedia.org/wiki/ISO_4217 ISO 4217}
	 * {@linkplain http://www.loc.gov/standards/iso639-2/englangn.html#st ISO 639}
	 * {@linkplain http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html ISO 3166}	 * 
	 * 
	 * Ejemplos:
	 * ---------
	 * 
	 * LRSConvertionTools.toString(213.21251D,"999999999900.00") retorna 213,21
	 * LRSConvertionTools.toString(0.21251D,"999999999999.00")   retorna ,21
	 * LRSConvertionTools.toString(0.21251D,"99999999990.00")    retorna 0,21
	 * LRSConvertionTools.toString(2321321.2D,"99999999990.00")  retorna 22.321.321,20
	 * LRSConvertionTools.toString(2321321.2D,"00.00")           retorna 21,20
	 * LRSConvertionTools.toString(1.2D,"0000.00")               retorna 0.001,20
	 * LRSConvertionTools.toString(1.2897987D,"0000.0099")       retorna 0.001,2898
	 * LRSConvertionTools.toString(22.2897987D,"99999")          retorna 22
	 * <pre>
	 * @param parNumero El numero a convertir
	 * @param mascara La mascara para hacer la conversion
	 * @param idioma Idioma (ISO 639-1)
	 * @param pais Pais (ISO 3166-1)
	 * @param curr La moneda (ISO 4217)
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static double toDouble(String parNumero, String mascara, String idioma, String pais, String curr)
	throws Exception{
		if (mascara == null)
			return 0;
		//Busco el punto.
		int punto = mascara.indexOf(".");
		if (punto == -1)
			punto = mascara.length();
		
		//Obtengo los parametros de la parte entera
		String entero = mascara.substring(0,punto);
		int intMax = entero.length();
		int intMin = (entero.indexOf("0") != -1 ? entero.length() - entero.indexOf("0") : 0);
		
		//Obtengo los parametros de la parte fraccionaria
		String fraccion = null;
		int fracMin = 0;
		int fracMax = 0;
		
		if (punto<mascara.length()){
			fraccion = mascara.substring(punto+1);
			fracMax = fraccion.length();
			if (fraccion.indexOf("9") != -1)
				fracMin = fraccion.indexOf("9");
			else
				fracMin = fraccion.length();
		}
			
		//Realizo la conversion
		return toDouble(parNumero,intMin,intMax,fracMin,fracMax,idioma,pais,curr);
	}
	
	/**
	 * <pre>
	 * Este metodo convierte un numero en double a un string siguiendo e interpretando una
	 * mascara en particular que debera armarse con una parte entera, una parte fraccionada
	 * ambas separadas por puntos.
	 * Los digitos deberan indicarse con un 9 que significa que el digito existe pero si no 
	 * esta presente en el numero que no lo coloque y el 0 indica que el digito se coloque
	 * igual, este o no este en el numero.
	 * Si no se coloca la parte fraccionaria, entonces se asume el numero como entero
	 * 
	 * Tiene en cuenta las especificaciones del idioma, el pais y la moneda
	 * 
	 * El idioma, es un codigo ISO 639-1 de 2 caracteres en minuscula.
	 * El pais, es un codigo ISO 3166-1 de 2 caracteres en mayusculas.
	 * El uso de la moneda es un codigo ISO 4217 de 3 caracteres en mayusculas.
	 * {@linkplain http://es.wikipedia.org/wiki/ISO_4217 ISO 4217}
	 * {@linkplain http://www.loc.gov/standards/iso639-2/englangn.html#st ISO 639}
	 * {@linkplain http://www.iso.ch/iso/en/prods-services/iso3166ma/02iso-3166-code-lists/list-en1.html ISO 3166}	 * 
	 * 
	 * Ejemplos:
	 * ---------
	 * 
	 * LRSConvertionTools.toString(213.21251D,"999999999900.00") retorna 213,21
	 * LRSConvertionTools.toString(0.21251D,"999999999999.00")   retorna ,21
	 * LRSConvertionTools.toString(0.21251D,"99999999990.00")    retorna 0,21
	 * LRSConvertionTools.toString(2321321.2D,"99999999990.00")  retorna 22.321.321,20
	 * LRSConvertionTools.toString(2321321.2D,"00.00")           retorna 21,20
	 * LRSConvertionTools.toString(1.2D,"0000.00")               retorna 0.001,20
	 * LRSConvertionTools.toString(1.2897987D,"0000.0099")       retorna 0.001,2898
	 * LRSConvertionTools.toString(22.2897987D,"99999")          retorna 22
	 * <pre>
	 * @param parNumero El numero a convertir
	 * @param mascara La mascara para hacer la conversion
	 * @param idioma Idioma (ISO 639-1)
	 * @param pais Pais (ISO 3166-1)
	 * @param curr La moneda (ISO 4217)
	 * @return El numero convertido
	 * @throws Exception En caso de que algun error ocurra
	 */
	public static String toString(double parNumero, String mascara, String idioma, String pais, String curr)
	throws Exception{
		if (mascara == null)
			return null;
		//Busco el punto.
		int punto = mascara.indexOf(".");
		if (punto == -1)
			punto = mascara.length();
		
		//Obtengo los parametros de la parte entera
		String entero = mascara.substring(0,punto);
		int intMax = entero.length();
		int intMin = (entero.indexOf("0") != -1 ? entero.length() - entero.indexOf("0") : 0);
		
		//Obtengo los parametros de la parte fraccionaria
		String fraccion = null;
		int fracMin = 0;
		int fracMax = 0;
		
		if (punto<mascara.length()){
			fraccion = mascara.substring(punto+1);
			fracMax = fraccion.length();
			if (fraccion.indexOf("9") != -1)
				fracMin = fraccion.indexOf("9");
			else
				fracMin = fraccion.length();
		}
			
		//Realizo la conversion
		return toString(parNumero,intMin,intMax,fracMin,fracMax,idioma,pais,curr);
	}
}
